package weaver.splittable.biz.workflow;

import org.apache.log4j.Logger;
import weaver.conn.*;
import weaver.splittable.STConfig;
import weaver.splittable.STContext;
import weaver.splittable.biz.STBizConfig;
import weaver.splittable.biz.STBizDataCleaner;
import weaver.splittable.biz.STBizInitializer;
import weaver.splittable.biz.STBizInterceptor;
import weaver.splittable.db.STDBSupport;
import weaver.splittable.db.STDBUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class STWorkflowInitializer implements STBizInitializer {

    private static final Logger LOGGER = Logger.getLogger(STConfig.LOGGER_NAME);
    private String bizName = "workflow";
    @Override
    public STBizConfig register() {
        Map<String, String> splitTables = STWorkflowConstants.SPLIT_TABLES;
        STBizInterceptor bizInterceptor = new STWorkflowInterceptor();
        STBizDataCleaner bizDataCleaner = new STWorkflowDataCleaner();
        return new STBizConfig(bizName, splitTables, bizInterceptor, bizDataCleaner);
    }
    @Override
    public boolean isInitialized() {
        boolean isInitialized = true;
        ConnectionPool connectionPool = ConnectionPool.getInstance();
        WeaverConnection connection = null;
        try {
            connection = connectionPool.getConnection();
            for (String tableName: STWorkflowConstants.SPLIT_TABLES.keySet()) {
                String fullDataTableName = tableName + "_all";
                if (STDBSupport.ORACLE.equals(STConfig.DB_TYPE)) {
                    fullDataTableName = fullDataTableName.toUpperCase();
                }
                boolean tableIsExist = STDBUtil.checkTableIsExist(fullDataTableName, connection);
                isInitialized = isInitialized && tableIsExist;
            }
        } catch (Exception e) {
            LOGGER.error("STWorkflowInitializer isInitialized error:", e);
        } finally {
            if (connection != null) {
                connectionPool.returnConnection(connection);
            }
        }
        return isInitialized;
    }

    @Override
    public void init() {
        //initSTWorkflowIndexes();
        initSTWorkflowTriggers();
    }

    @Override
    public String getBizName() {
        return this.bizName;
    }

    //有些表数据过大创建索引会超时，暂时放弃
    private void initSTWorkflowIndexes() {
        LOGGER.info("初始化流程全量表索引");
        ConnectionPool connectionPool = ConnectionPool.getInstance();
        WeaverConnection connection = null;
        WeaverStatement statement = null;
        try {
            connection = connectionPool.getConnection();
            statement = (WeaverStatement) connection.createStatement();
            for (String createIndexSql: getCreateIndexSqls()) {
                try {
                    statement.originExecuteUpdate(createIndexSql);
                } catch (Exception e) {
                    LOGGER.error(createIndexSql + " error:", e);
                }
            }
        } catch (Exception e) {
            LOGGER.error("STWorkflowInitializer initSTWorkflowIndexes error:", e);
        } finally {
            if (statement != null) {
                statement.closeNoException();
            }
            if (connection != null) {
                connectionPool.returnConnection(connection);
            }
        }
    }

    private void initSTWorkflowTriggers() {
        LOGGER.info("初始化流程活跃表触发器");
        ConnectionPool connectionPool = ConnectionPool.getInstance();
        WeaverConnection connection = null;
        WeaverStatement statement = null;
        try {
            connection = connectionPool.getConnection();
            statement = (WeaverStatement) connection.createStatement();
            for (String createTriggerSql: getCreateTriggerSqls()) {
                try {
                    statement.originExecuteUpdate(createTriggerSql);
                } catch (Exception e) {
                    LOGGER.error(createTriggerSql + " error:", e);
                }
            }
        } catch (Exception e) {
            LOGGER.error("STWorkflowInitializer initSTWorkflowTriggers error:", e);
        } finally {
            if (statement != null) {
                statement.closeNoException();
            }
            if (connection != null) {
                connectionPool.returnConnection(connection);
            }
        }
    }

    private List<String> getCreateIndexSqls() {
        List<String> indexSQLs = new ArrayList<>();

        // workflow_requestbase
        String workflowRequestBaseTableName = "workflow_requestbase_all";
        String idxWrbaRequestIdStatusSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_rids", workflowRequestBaseTableName, Arrays.asList("REQUESTID", "STATUS"));
        String idxWrbaRequestLevelSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_rlevel", workflowRequestBaseTableName, Arrays.asList("REQUESTLEVEL"));
        String idxWrbaRequestIdSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_rid", workflowRequestBaseTableName, Arrays.asList("REQUESTID"));
        String idxWrbaMainRequestIdSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_mrid", workflowRequestBaseTableName, Arrays.asList("MAINREQUESTID"));
        String idxWrbaWorkflowIdRequestIdSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_widrid", workflowRequestBaseTableName, Arrays.asList("WORKFLOWID", "REQUESTID"));
        String idxWrbaCreaterCreaterTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wrba_crcrt", workflowRequestBaseTableName, Arrays.asList("CREATER", "CREATERTYPE"));
        indexSQLs.add(idxWrbaRequestIdStatusSQL);
        indexSQLs.add(idxWrbaRequestLevelSQL);
        indexSQLs.add(idxWrbaRequestIdSQL);
        indexSQLs.add(idxWrbaMainRequestIdSQL);
        indexSQLs.add(idxWrbaWorkflowIdRequestIdSQL);
        indexSQLs.add(idxWrbaCreaterCreaterTypeSQL);

        // workflow_currentoperator
        String workflowCurrentOperatorTableName = "workflow_currentoperator_all";
        String idxWcoaRequestIdNodeIdSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_ridnid", workflowCurrentOperatorTableName, Arrays.asList("REQUESTID", "NODEID"));
        String idxWcoaIdSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_id", workflowCurrentOperatorTableName, Arrays.asList("ID"));
        String idxWcoaUserIdRequestIdSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_uidrid", workflowCurrentOperatorTableName, Arrays.asList("USERID", "REQUESTID"));
        String idxWcoaRequestIdUserIdWorkflowIdSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_riduidwid", workflowCurrentOperatorTableName, Arrays.asList("REQUESTID", "USERID", "WORKFLOWID"));
        String idxWcoaRequestIdUserIdUserTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_riduidut", workflowCurrentOperatorTableName, Arrays.asList("REQUESTID", "USERID", "USERTYPE"));
        String idxWcoaIsRemarkTmpUserIdUserTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_irtuidut", workflowCurrentOperatorTableName, Arrays.asList("ISREMARK_TMP", "USERID", "USERTYPE"));
        String idxWcoaIsRemarkUserIdUserTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wcoa_iruidut", workflowCurrentOperatorTableName, Arrays.asList("ISREMARK", "USERID", "USERTYPE"));
        indexSQLs.add(idxWcoaRequestIdNodeIdSQL);
        indexSQLs.add(idxWcoaIdSQL);
        indexSQLs.add(idxWcoaUserIdRequestIdSQL);
        indexSQLs.add(idxWcoaRequestIdUserIdWorkflowIdSQL);
        indexSQLs.add(idxWcoaRequestIdUserIdUserTypeSQL);
        indexSQLs.add(idxWcoaIsRemarkTmpUserIdUserTypeSQL);
        indexSQLs.add(idxWcoaIsRemarkUserIdUserTypeSQL);

        // workflow_requestLog
        String workflowRequestLogTableName = "workflow_requestLog_all";
        String idxWrlaNodeIdRequestIdLogTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wrla_nidridlt", workflowRequestLogTableName, Arrays.asList("NODEID", "REQUESTID", "LOGTYPE"));
        String idxWrlaLogIdSQL = STContext.CREATE_INDEX().createIndex("idx_wrla_lid", workflowRequestLogTableName, Arrays.asList("LOGID"));
        String idxWrlaOperatorOperatorTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wrla_optroptrt", workflowRequestLogTableName, Arrays.asList("OPERATOR", "OPERATORTYPE"));
        String idxWrlaRequestIdLogTypeSQL = STContext.CREATE_INDEX().createIndex("idx_wrla_ridlt", workflowRequestLogTableName, Arrays.asList("REQUESTID", "LOGTYPE"));
        indexSQLs.add(idxWrlaNodeIdRequestIdLogTypeSQL);
        indexSQLs.add(idxWrlaLogIdSQL);
        indexSQLs.add(idxWrlaOperatorOperatorTypeSQL);
        indexSQLs.add(idxWrlaRequestIdLogTypeSQL);

        return indexSQLs;
    }

    public List<String> getCreateTriggerSqls() {
        List<String> triggerSQLs = new ArrayList<>();

        for (Map.Entry<String, String> tableEntry: STWorkflowConstants.SPLIT_TABLES.entrySet()) {
            String tableName = tableEntry.getKey();
            String dataIdColumn = tableEntry.getValue();

            String insertTriggerSQL = STContext.CREATE_TRIGGER().createTriggerInsert(tableName, dataIdColumn);
            String updateTriggerSQL = STContext.CREATE_TRIGGER().createTriggerUpdate(tableName, dataIdColumn);
            String deleteTriggerSQL = STContext.CREATE_TRIGGER().createTriggerDelete(tableName, dataIdColumn);
            triggerSQLs.add(insertTriggerSQL);
            triggerSQLs.add(updateTriggerSQL);
            triggerSQLs.add(deleteTriggerSQL);
        }
        return triggerSQLs;
    }

}
